iT邦幫忙

DAY 8
1

用程式描繪世界 - 閱讀The Nature of Code系列 第 8

[Day8] - 平滑移動 (Perlin Noise)

  • 分享至 

  • xImage
  •  

Perlin Noise

今天要介紹的就是Perlin Noise啦,前幾篇文章介紹過均勻分佈random()或是高斯分佈nextGaussian(),這兩種應用在隨機移動(Random Walk)上都是可行的,移動的路徑是隨機沒錯,但是有一點奇怪的是,移動的軌跡轉折的非常生硬,這一秒的位置與下一瞬間的位置之間毫無關係,這在自然界中很不尋常,你不會看到螢火蟲或蒼蠅這樣移動,通常移動的軌跡都是相關聯的,或者可以說是很平滑的。

這裡就有Perlin Noise的用武之地啦,

左邊是隨機生成的圖像,右邊的是使用Perlin noise生成的圖像

看出來了嗎,我們可以讓隨機的數值變得更加的smooth。

Processing內建有Perlin noise的function,只要使用noise(),noise()接受1~3的參數,取決於要使用幾個維度去計算noise,在這邊只會使用到一個維度。

random()這個function使用的方法是給定最大與最小值,在最大與最小值之間產生一個隨機值,但noise這個function的運作是完全不同的,無論如何他都是產生一個0~1的隨機值,隨機值得產生是依據傳進來的參數,如果傳進來的參數一樣,便會回傳一樣的結果。

所以在使用的時候要替換參數的值,參數變化的區間會影響數值變化的大小,

第一種參數:
noise(1) => 0.156051
noise(2) => 0.290425
noise(3) => 0.540645

參數間隔較小:
noise(0.01) => 0.386841
noise(0.02) => 0.388689
noise(0.03) => 0.391724

參數間隔較小的,回傳的結果之間會越有相關性,結論就是:
想要平滑一點就傳入的參數間隔就小一點啦,例如:0.001、0.002、0.003,非常平滑~

實際上在使用的時候可以在每次draw的時候增加參數的值,

float t = 0;

void draw() {
  float n = noise(t);
  println(n); //把n印到console上
  t += 0.01; //增加參數的值
}

程式跑起來,在每次畫面更新時改變t的值,就可以在console上看到noise數值的變化。

實際應用

在剛剛的程式碼,在實際上的情況無法直接使用,因為只會產生0~1的數值,這時候就必須將這noise()產生的數值,mapping到我們所需要的範圍,這時候可以直接套用map()這個function,

map( 要轉換的數值, 原範圍最小值, 原範圍最大值, 調整後最小值, 調整後最大值 )

所以假設情況是我們要將一個球套用Perlin Noise,在x軸上進行移動,概念是這樣的

map( noise_number, 0, 1, 0, 螢幕寬度 )

實際上程式碼:

float t = 0;

void draw() {
  float n = noise(t);
  float x = map(n,0,1,0,width); // 使用map改變noise的範圍
  ellipse(x,180,16,16);

  t += 0.01;
}

當然我們可以讓程式碼再進化,表演一個在空中飄移的球。這邊拿原本Random Walk的Class來使用

class Walker {
  float x,y;
  float tx,ty;

  Walker() {
    tx = 0;
    ty = 10000;
  }

  void step() {
    x = map(noise(tx), 0, 1, 0, width);
    y = map(noise(ty), 0, 1, 0, height);

    tx += 0.01;
    ty += 0.01;
  }
}

要注意的是,tx與ty起始值設為0與10000不一樣的值,這是因為上面所述,noise()這個function如果接受了一樣的參數,就會傳出一樣的值,我們必需讓x與y軸產生不一樣的隨機值。

結果如下:

gif不會動真是令人傷心 .... ,下一篇繼續介紹Perlin noise!!


上一篇
[Day7] - 來畫個圖吧,練習Distribution只是順便~
下一篇
[Day9] - 二維的Perlin Noise
系列文
用程式描繪世界 - 閱讀The Nature of Code9
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言